package com.world.spire.office.free;

import com.spire.doc.*;
import com.spire.doc.documents.*;
import com.spire.doc.fields.DocPicture;
import com.spire.doc.fields.TextRange;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.awt.*;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 创建人: wll
 * 创建日期: 2023-04-06
 * 功能描述: spire 进行word数据填充
 */
public class SpireUtils {

    /**
     * The constant LOG.
     */
    private static final Logger LOG = LoggerFactory.getLogger(SpireUtils.class);

    private static float autograph = 50;  //签名尺寸

    private static float seal = 90;   //盖章尺寸

    //private static final String MODEL_PATH = String.format("%s%s%s", "settle_spire", File.separator, "model");

    //private static final String OUT_PATH = String.format("%s%s%s", "settle_spire");

    /**
     * spire word 替换文字/图片。
     *
     * @param id     业务id
     * @param url    模板名称
     * @param params {
     *               "key":"$年份$",要替换的占位符，
     *               "value":"2020",要替换的值，
     *               "type":"1/2"   签名/盖章
     *               "h_pos":300    //横向偏移
     *               "v_pos":50    //纵向偏移
     *               图片value为$pic:+图片路径
     *               }
     * @return
     */
    public static String basePath = System.getProperty("user.dir") + File.separator +"doc" + File.separator + "upload" ;

    public static String spireReplace(String id, String url, List<Map> params, String modelType) {
//        String strogePath = "c:/fweb-sign/model";
//        //String filePathType = "fweb-sign.file.win";
//        if (null != System.getProperties().getProperty("os.name")
//                && System.getProperties().getProperty("os.name").toLowerCase().indexOf("linux") > -1) {
//            //   filePathType = "fweb-sign.file.linux";
//            strogePath = "/usr/etc/fweb-sign/model";
//        }
        //String strogePath = ConfigHelper.getPluginConfig(filePathType, "fweb-sign");
        String file_word_path = String.format("%s%s%s", basePath, File.separator, id);
        //模板地址
        String outUrl = String.format("%s%s", file_word_path, ".doc");
        String pdfUrl = String.format("%s%s", file_word_path, ".pdf");
        try {
            Document doc = new Document();
            doc.loadFromFile(url);
            for (int i = 0; i < params.size(); i++) {
                String value;
                if(params.get(i) != null &&  params.get(i).get("value") != null){
                     value = params.get(i).get("value").toString();
                }else {
                    value = "";
                }
                String key = "$" + params.get(i).get("key") + "$";
                if (value.startsWith("$pic:")) {
                    String type = (String) params.get(i).get("type");
                    String h_pos = (String) params.get(i).get("hPos");
                    String v_pos = (String) params.get(i).get("vPos");
                    value = value.substring(5);
                    TextSelection pics = doc.findString(key, true, true);
                    //用图片替换文字
                    int index = 0;
                    TextRange range = null;
                    TextSelection textSelection = (TextSelection) pics;
                    DocPicture pic = new DocPicture(doc);
                    //拿到签章的图片地址
                    pic.loadImage(value);
                    range = textSelection.getAsOneRange();
                    pic.setTextWrappingStyle(TextWrappingStyle.None);
                    float displayWidth = type.equals("1") ? autograph : seal;
                    float zoomRate = displayWidth / pic.getWidth();//缩放比例
                    float displayHeigth = pic.getHeight() * zoomRate;//显示高度
                    pic.setWidth(displayWidth);
                    pic.setHeight(displayHeigth);
                    pic.setVerticalPosition(!StringUtils.isEmpty(v_pos) ? Float.valueOf(v_pos) : 0);   //纵向
                    pic.setHorizontalPosition(!StringUtils.isEmpty(h_pos) ? Float.valueOf(h_pos) : 0);    //横向
                    index = range.getOwnerParagraph().getChildObjects().indexOf(range);
                    range.getOwnerParagraph().getChildObjects().insert(index, pic);
                    range.getOwnerParagraph().getChildObjects().remove(range);
                } else if ("qrcode".equals(params.get(i).get("key"))) {
                    TextSelection pics = doc.findString(key, true, true);
                    int index = 0;
                    TextRange range = null;
                    TextSelection textSelection = (TextSelection) pics;
                    DocPicture pic = new DocPicture(doc);
                    pic.loadImage(value);
                    range = textSelection.getAsOneRange();
                    pic.setTextWrappingStyle(TextWrappingStyle.None);
                    float zoomRate = 50 / pic.getWidth();//缩放比例
                    float displayHeigth = pic.getHeight() * zoomRate;//显示高度
                    pic.setWidth(50);
                    pic.setHeight(displayHeigth);
                    pic.setVerticalPosition(-25);   //纵向
                    pic.setHorizontalPosition(400);    //横向
                    index = range.getOwnerParagraph().getChildObjects().indexOf(range);
                    range.getOwnerParagraph().getChildObjects().insert(index, pic);
                    range.getOwnerParagraph().getChildObjects().remove(range);
                } else if ("qrcodeunfinished".equals(params.get(i).get("key"))) {
                    doc.replace("$qrcode$", "", false, true);
                } else {
                    doc.replace(key, value, false, true);
                }
            }
            doc.saveToFile(outUrl, FileFormat.Docx_2013);
            OfficeToPdfUtils.word2Pdf(outUrl, pdfUrl);
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            //删除临时word文件
            File file = new File(outUrl);
            if (file.exists()) {
                file.delete();
            }
        }
        return pdfUrl;

    }


    public static void main(String[] args) throws Exception {
        //spireReplace("C:\\Users\\pc\\Desktop\\1.doc", "C:\\Users\\pc\\Desktop\\2.doc", list);
        //spireReplace("C:\\Users\\pc\\Desktop\\1.doc", "C:\\Users\\pc\\Desktop\\2.doc", list);
        //OfficeToPdfUtils.word2Pdf("C:\\Users\\pc\\Desktop\\2.doc","C:\\Users\\pc\\Desktop\\2.pdf");
        //doc.save("C:\\Users\\pc\\Desktop\\2.doc");


        String basePath = "C:\\Users\\Administrator\\Desktop\\test\\";
        String tempPath = basePath + "temp.doc";
        //普通字符串替换
//        mapData.put("", "北京水电工程");
//        mapData.put("dataDate", "");
//        mapData.put("code", "");
//        mapData.put("shigong", "咳咳");
//        mapData.put("jianguan", "呵呵");
        //""
        List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();
        initData(data);
        worldBindData(tempPath, basePath, data);
        System.out.println("完成！！！！！！！！！！！");
    }

    public static void initData(List<Map<String, Object>> data) {
        String baseImagePath = "C:\\Users\\Administrator\\Pictures\\";
        // 普通字符串
        data.add(new HashMap<String, Object>() {{
            put("key", "projectName");
            put("type", "string");
            put("value", "*****************工程");
        }});
        data.add(new HashMap<String, Object>() {{
            put("key", "dataDate");
            put("type", "string");
            put("value", "2023年1月12号");
        }});
        data.add(new HashMap<String, Object>() {{
            put("key", "code");
            put("type", "string");
            put("value", "10002");
        }});

        // 图片
        data.add(new HashMap<String, Object>() {{
            put("key", "image1");
            put("type", "image");
            put("value", baseImagePath + "0.png");
        }});
//        data.add(new HashMap<String, Object>() {{
//            put("key", "image2");
//            put("type", "image");
//            put("value", baseImagePath + "112.png");
//        }});
//        data.add(new HashMap<String, Object>() {{
//            put("key", "image3");
//            put("type", "image");
//            put("value", baseImagePath + "111.png");
//        }});
//        data.add(new HashMap<String, Object>() {{
//            put("key", "shigong");
//            put("type", "image");
//            put("value", baseImagePath + "5.png");
//        }});
//        data.add(new HashMap<String, Object>() {{
//            put("key", "jianguan");
//            put("type", "image");
//            put("value", baseImagePath + "6.png");
//        }});

        // 表格数据
        List<Map<String, Object>> students = new ArrayList<>();
        List<String> studentColKeys = new ArrayList<String>() {{
            add("stuNo");
            add("name");
            add("sex");
        }};

        students.add(new HashMap<String, Object>() {{
            put("stuNo", "1");
            put("name", "张三");
            put("sex", "男");
        }});
        students.add(new HashMap<String, Object>() {{
            put("stuNo", "2");
            put("name", "李四");
            put("sex", "女");
        }});

        students.add(new HashMap<String, Object>() {{
            put("stuNo", "3");
            put("name", "赵武");
            put("sex", "男");
        }});

        data.add(new HashMap<String, Object>() {{
            put("key", "");
//            put("tableHeaders", "");
            put("type", "table");
            put("tableType", "temp");
            put("tableIndex", 0);
            put("tableColumnKeys", studentColKeys);
            put("value", students);
        }});


        List<Map<String, Object>> teachers = new ArrayList<>();
        List<String> teacherColKeys = new ArrayList<String>() {{
            add("teaNo");
            add("name");
            add("sex");
        }};

        teachers.add(new HashMap<String, Object>() {{
            put("teaNo", "1");
            put("name", "张美丽");
            put("sex", "女");
        }});
        teachers.add(new HashMap<String, Object>() {{
            put("teaNo", "2");
            put("name", "李铁");
            put("sex", "男");
        }});

        teachers.add(new HashMap<String, Object>() {{
            put("teaNo", "3");
            put("name", "赵武刚");
            put("sex", "男");
        }});

        data.add(new HashMap<String, Object>() {{
            put("key", "");
            put("type", "table");
            put("tableType", "temp");
            put("tableIndex", 1);
            put("tableColumnKeys", teacherColKeys);
            put("value", teachers);
        }});

        data.add(new HashMap<String, Object>() {{
            put("key", "students");
            put("type", "table");
            put("tableType", "tabs");
//            put("tableIndex", 0);
            put("tableHeaders", new ArrayList<String>() {{
                add("学生学号");
                add("姓名");
                add("性别");
            }});
            put("tableColumnKeys", studentColKeys);
            put("value", students);

        }});

        data.add(new HashMap<String, Object>() {{
            put("key", "teachers");
            put("type", "table");
            put("tableType", "tring");
//            put("tableIndex", 0);
            put("tableColumnKeys", teacherColKeys);
            put("tableHeaders", new ArrayList<String>() {{
                add("老师工号");
                add("姓名");
                add("性别");
            }});
            put("value", teachers);
        }});

    }

    /**
     * world 绑定数据
     * 参考地址  https://www.e-iceblue.cn/docjava/add-row-and-column-to-table-in-word-using-java.html
     *
     * @param tempPath
     * @param outPath
     * @param data
     */
    public static void worldBindData(String tempPath, String outPath, List<Map<String, Object>> data) {
        Document doc = new Document();
        doc.loadFromFile(tempPath, FileFormat.Doc);
        // 文字替换
        if (data != null && data.size() > 0) {
            for (int i = 0; i < data.size(); i++) {
                Map<String, Object> map = data.get(i);
                String type = map.get("type").toString();
                String key = "";
                if (map.get("key") != null) {
                    key = "$" + map.get("key").toString() + "$";
                }
                switch (type) {
                    case "image":
                        TextSelection pics = doc.findString(key, true, true);
                        //用图片替换文字
                        int index = 0;
                        TextRange range = null;
                        TextSelection textSelection = (TextSelection) pics;
                        DocPicture pic = new DocPicture(doc);
                        //拿到签章的图片地址
                        pic.loadImage(map.get("value").toString());
                        range = textSelection.getAsOneRange();
                        pic.setTextWrappingStyle(TextWrappingStyle.None);
                        float displayWidth = type.equals("1") ? autograph : seal;
                        float zoomRate = displayWidth / pic.getWidth();//缩放比例
                        float displayHeigth = pic.getHeight() * zoomRate;//显示高度
                        pic.setWidth(displayWidth);
                        pic.setHeight(displayHeigth);
//                        pic.setVerticalPosition(StringUtils.isNotEmpty(v_pos) ? Float.valueOf(v_pos) : 0);   //纵向
//                        pic.setHorizontalPosition(StringUtils.isNotEmpty(h_pos) ? Float.valueOf(h_pos) : 0);    //横向
                        index = range.getOwnerParagraph().getChildObjects().indexOf(range);
                        range.getOwnerParagraph().getChildObjects().insert(index, pic);
                        range.getOwnerParagraph().getChildObjects().remove(range);
                        //图片保存测试
//                        TextSelection[] textSelection = doc.findAllString(key, true, false);
//                        Integer width = (Integer) map.get("width");
//                        if (width == null || ObjectUtil.isEmpty(width)) {
//                            width = 50;
//                        }
//                        Integer height = (Integer) map.get("height");
//                        if (height == null || ObjectUtil.isEmpty(height)) {
//                            height = 50;
//                        }
                        //加载图片替换文本字符串
//                        for (Object obj : textSelection) {
//                            TextSelection Selection = (TextSelection) obj;
//                            DocPicture pic = new DocPicture(doc);
//                            pic.loadImage(map.get("value").toString());
//                            pic.setWidth(width);
//                            pic.setHeight(height);
//                            TextRange range = Selection.getAsOneRange();
//                            index = range.getOwnerParagraph().getChildObjects().indexOf(range);
//                            range.getOwnerParagraph().getChildObjects().insert(index, pic);
//                            range.getOwnerParagraph().getChildObjects().remove(range);
//                        }
                        break;
                    case "table":
                        List<Map<String, Object>> tableData = (List<Map<String, Object>>) map.get("value");
                        Integer tableIndex = (Integer) map.get("tableIndex");
                        List<String> columnKeys = (List<String>) map.get("tableColumnKeys");
                        List<String> headers = (List<String>) map.get("tableHeaders");
                        String tableType = map.get("tableType").toString();
                        if ("temp".equals(tableType)) {
                            // 模板
                            insertTableByTemp(doc, tableData, columnKeys, tableIndex);
                        }
                        if ("tabs".equals(tableType)) {
                            // 书签
                            insertTableByTabs(doc, map.get("key").toString(), tableData, columnKeys, headers);
                        }
                        if ("string".equals(tableType)) {
                            // 字符串
                            insertTableByString(doc, map.get("key").toString(), tableData, columnKeys, headers);
                        }
                        break;
                    case "string":
                        doc.replace(key, map.get("value").toString(), true, true);
                        break;
                    default:
                        doc.replace(key, map.get("value").toString(), true, true);
                }
            }
        }
        long timeMillis = System.currentTimeMillis();
        String outUrl = outPath + timeMillis + ".doc";
        String pdfUrl = outPath + timeMillis + ".pdf";
        doc.saveToFile(outUrl, FileFormat.Docx_2013);
        OfficeToPdfUtils.word2Pdf(outUrl, pdfUrl);
    }


    /**
     * 方法一插入表格 模板中创建好表格 表格追加数据
     */
    public static void insertTableByTemp(Document doc, List<Map<String, Object>> tableData, List<String> columsKeys, Integer tableIndex) {
        Section section = doc.getSections().get(0);
        Table table = section.getTables().get(tableIndex);
        TableRow headerRow = table.getRows().get(0);
        headerRow.isHeader(true);
        headerRow.setHeight(20);
        headerRow.setHeightType(TableRowHeightType.Exactly);
        headerRow.getRowFormat().setBackColor(Color.white);
        //绘制表头
        for (int i = 0; i < columsKeys.size(); i++) {
            headerRow.getCells().get(i).getCellFormat().setVerticalAlignment(VerticalAlignment.Middle);
            Paragraph p = headerRow.getCells().get(i).addParagraph();
            p.getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
            TextRange range1 = p.appendText(p.getText());
            range1.getCharacterFormat().setFontName("Arial");
            range1.getCharacterFormat().setFontSize(12f);
            range1.getCharacterFormat().setBold(true);
            range1.getCharacterFormat().setTextColor(Color.BLACK);
        }
        //写入剩余组内容到表格，并格式化数据
        // row
        for (int r = 0; r < tableData.size(); r++) {
            TableRow dataRow = table.addRow(true, columsKeys.size());
            dataRow.setHeight(25);
            dataRow.setHeightType(TableRowHeightType.Exactly);
            dataRow.getRowFormat().setBackColor(Color.white);
            // col
            for (int c = 0; c < columsKeys.size(); c++) {
                dataRow.getCells().get(c).getCellFormat().setVerticalAlignment(VerticalAlignment.Middle);
                TextRange range = dataRow.getCells().get(c).addParagraph().appendText(tableData.get(r).get(columsKeys.get(c).toString()).toString());
                range.getCharacterFormat().setFontName("Arial");
                range.getCharacterFormat().setFontSize(10f);
                dataRow.getRowFormat().setHorizontalAlignment(RowAlignment.Center);
                dataRow.getCells().get(c).getCellFormat().setVerticalAlignment(VerticalAlignment.Middle);
            }
        }
    }

    /**
     * 方法二插入表格 模板中创建书签位置插入表格  (world  插入书签 )
     */
    public static void insertTableByTabs(Document doc, String key, List<Map<String, Object>> tableData, List<String> columsKeys, List<String> headers) {
        //创建表格
        Table table = new Table(doc, true);
        // 重置 设置 行数 列数
        table.resetCells(tableData.size(), columsKeys.size());
        // 创建表头
        TableRow headerRow = table.getRows().get(0);
        headerRow.isHeader(true);
        headerRow.setHeight(20);
        headerRow.setHeightType(TableRowHeightType.Exactly);
        headerRow.getRowFormat().setBackColor(Color.white);
        //绘制表头
        for (int i = 0; i < headers.size(); i++) {
            headerRow.getCells().get(i).getCellFormat().setVerticalAlignment(VerticalAlignment.Middle);
            Paragraph p = headerRow.getCells().get(i).addParagraph();
            p.getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
            TextRange range1 = p.appendText(headers.get(i).toString());
            range1.getCharacterFormat().setFontName("Arial");
            range1.getCharacterFormat().setFontSize(12f);
            range1.getCharacterFormat().setBold(true);
            range1.getCharacterFormat().setTextColor(Color.BLACK);
        }
        // 填充数据
        for (int r = 1; r < tableData.size(); r++) {
            TableRow dataRow = table.getRows().get(r);
            dataRow.setHeight(25);
            dataRow.setHeightType(TableRowHeightType.Exactly);
            dataRow.getRowFormat().setBackColor(Color.white);
            for (int c = 0; c < columsKeys.size(); c++) {
                TextRange range = dataRow.getCells().get(c).addParagraph().appendText(tableData.get(r).get(columsKeys.get(c).toString()).toString());
                range.getOwnerParagraph().getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
                range.getCharacterFormat().setFontName("Arial");
                range.getCharacterFormat().setFontSize(10f);
                dataRow.getRowFormat().setHorizontalAlignment(RowAlignment.Center);
                dataRow.getCells().get(c).getCellFormat().setVerticalAlignment(VerticalAlignment.Middle);
            }
        }
        //定位到指定书签位置,添加表格
        BookmarksNavigator bookmarksNavigator = new BookmarksNavigator(doc);
        bookmarksNavigator.moveToBookmark(key);
        bookmarksNavigator.insertTable(table);
    }

    /**
     * 方法三插入表格 模板中创建占位字符串替换插入表格
     */
    public static void insertTableByString(Document doc, String key, List<Map<String, Object>> tableData, List<String> columsKeys, List<String> headers) {
        // 对读取到的源文件中，包含  $tables$  的文字进行表格替换操作 ，
        // 如果如果不需要全局替换，只替换一个，请参照上文图片处所备注的方法即可
        Section section = doc.getSections().get(0);
        TextSelection[] selections = doc.findAllString(key, true, true);
        for (TextSelection selection : selections) {
            //获取关键字符串所在段落的索引
            TextRange range = selection.getAsOneRange();
            Paragraph paragraph = range.getOwnerParagraph();
            Body body = paragraph.ownerTextBody();
            int index = body.getChildObjects().indexOf(paragraph);
            //创建表格
            Table table = section.addTable(true);
            // 重置 设置 行数 列数
            table.resetCells(tableData.size(), columsKeys.size());
            // 创建表头
            TableRow headerRow = table.getRows().get(0);
            headerRow.isHeader(true);
            headerRow.setHeight(20);
            headerRow.setHeightType(TableRowHeightType.Exactly);
            headerRow.getRowFormat().setBackColor(Color.white);
            //绘制表头
            for (int i = 0; i < headers.size(); i++) {
                headerRow.getCells().get(i).getCellFormat().setVerticalAlignment(VerticalAlignment.Middle);
                Paragraph p = headerRow.getCells().get(i).addParagraph();
                p.getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
                TextRange range1 = p.appendText(headers.get(i).toString());
                range1.getCharacterFormat().setFontName("Arial");
                range1.getCharacterFormat().setFontSize(12f);
                range1.getCharacterFormat().setBold(true);
                range1.getCharacterFormat().setTextColor(Color.BLACK);
            }
            // 填充数据
            for (int r = 1; r < tableData.size(); r++) {
                TableRow dataRow = table.getRows().get(r);
                dataRow.setHeight(25);
                dataRow.setHeightType(TableRowHeightType.Exactly);
                dataRow.getRowFormat().setBackColor(Color.white);
                for (int c = 0; c < columsKeys.size(); c++) {
                    TextRange range2 = dataRow.getCells().get(c).addParagraph().appendText(tableData.get(r).get(columsKeys.get(c).toString()).toString());
                    range2.getOwnerParagraph().getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
                    range2.getCharacterFormat().setFontName("Arial");
                    range2.getCharacterFormat().setFontSize(10f);
                    dataRow.getRowFormat().setHorizontalAlignment(RowAlignment.Center);
                    dataRow.getCells().get(c).getCellFormat().setVerticalAlignment(VerticalAlignment.Middle);
                }
            }
            //移除段落，插入表格
            body.getChildObjects().remove(paragraph);
            body.getChildObjects().insert(index, table);
        }
    }


}
